import 'dart:async';
import 'dart:math';

import 'package:detect/notifier/fpga_time.dart';
import 'package:detect/utils/global.dart';
import 'package:detect/widgets/resize_state_builder.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_color_plugin/flutter_color_plugin.dart';
import 'package:flutter_keyboard_visibility/flutter_keyboard_visibility.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:provider/provider.dart';

class ModalUtil {
  ModalUtil._();

  static Future<DateTime?> dateTime({
    required BuildContext context,
    CupertinoDatePickerMode mode = CupertinoDatePickerMode.time,
    int days = 30,
    String? title,
  }) async {
    DateTime now = context.read<FpgaTimeNotifier>().now, selectedDateTime = now;
    return ModalUtil.dialog<DateTime>(
      context: context,
      width: Global.ds(400),
      height: Global.ds(300),
      borderRadius: BorderRadius.circular(Global.ds(8)),
      barrierDismissible: false,
      child: Padding(
        padding: EdgeInsets.all(Global.ds(15)),
        child: Column(
          mainAxisSize: MainAxisSize.min,
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            Center(
              child: Text(
                title ??
                    (mode == CupertinoDatePickerMode.date
                        ? "选择日期"
                        : mode == CupertinoDatePickerMode.time
                            ? "选择时间"
                            : "选择日期时间"),
                style: TextStyle(
                  fontSize: Global.ds(20),
                  color: ColorUtil.color("#303133"),
                  decoration: TextDecoration.none,
                ),
              ),
            ),
            Divider(height: Global.ds(10), color: Colors.transparent),
            Expanded(
              child: CupertinoDatePicker(
                mode: mode,
                use24hFormat: true,
                initialDateTime: now,
                dateOrder: DatePickerDateOrder.ymd,
                onDateTimeChanged: (dateTime) => selectedDateTime = dateTime,
              ),
            ),
            Divider(height: Global.ds(10), color: Colors.transparent),
            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                TextButton(
                  onPressed: () => Navigator.pop<DateTime>(context),
                  style: TextButton.styleFrom(
                    foregroundColor: Colors.white,
                    backgroundColor: ColorUtil.color("#9B9B9B"),
                    fixedSize: Size(Global.ds(100), Global.ds(36)),
                    textStyle: TextStyle(fontSize: Global.ds(16)),
                  ),
                  child: const Text("取消"),
                ),
                VerticalDivider(width: Global.ds(20), color: Colors.transparent),
                TextButton(
                  onPressed: () => Navigator.pop<DateTime>(context, selectedDateTime),
                  style: TextButton.styleFrom(
                    foregroundColor: Colors.white,
                    backgroundColor: ColorUtil.color("#00497B"),
                    fixedSize: Size(Global.ds(100), Global.ds(36)),
                    textStyle: TextStyle(fontSize: Global.ds(16)),
                  ),
                  child: const Text("确定"),
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }

  static Future<bool?> confirm({
    String title = '操作确认',
    String content = '确认操作',
  }) {
    return SmartDialog.show<bool>(
      builder: (context) => Container(
        width: Global.ds(360),
        clipBehavior: Clip.antiAlias,
        padding: EdgeInsets.all(Global.ds(20)),
        decoration: BoxDecoration(color: ColorUtil.color("#1A3959"), borderRadius: BorderRadius.circular(Global.ds(16))),
        child: Column(
          mainAxisSize: MainAxisSize.min,
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            Text(title, textAlign: TextAlign.center, style: TextStyle(fontSize: Global.ds(24), color: ColorUtil.color("#D95348"), fontWeight: FontWeight.w700)),
            Divider(height: Global.ds(20), color: Colors.transparent),
            Text(content, textAlign: TextAlign.center, style: TextStyle(fontSize: Global.ds(18), color: Colors.white)),
            Divider(height: Global.ds(40), color: Colors.transparent),
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: [
                TextButton(
                  onPressed: () => SmartDialog.dismiss(status: SmartStatus.custom, result: false),
                  style: TextButton.styleFrom(
                    textStyle: TextStyle(fontSize: Global.ds(18)),
                    fixedSize: Size(Global.ds(120), Global.ds(40)),
                    foregroundColor: ColorUtil.color("#687079"),
                    backgroundColor: ColorUtil.color("#1A263D"),
                  ),
                  child: const Text("取消"),
                ),
                TextButton(
                  onPressed: () => SmartDialog.dismiss(status: SmartStatus.custom, result: true),
                  style: TextButton.styleFrom(
                    textStyle: TextStyle(fontSize: Global.ds(18)),
                    fixedSize: Size(Global.ds(120), Global.ds(40)),
                    foregroundColor: Colors.white,
                    backgroundColor: ColorUtil.color("#2CA6E0"),
                  ),
                  child: const Text("确定"),
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }

  static Future<T?> drawer<T>({
    required BuildContext context,
    required String title,
    required Widget child,
    double? width,
    double padding = 0,
    double radius = 0,
    Color backgroundColor = Colors.white,
    barrierDismissible = true,
    double opacity = .55,
    bool useRootNavigator = false,
    Duration transitionDuration = const Duration(milliseconds: 300),
    bool resizeToAvoidBottomInset = true,
    RouteTransitionsBuilder? transitionBuilder,
    String? barrierLabel,
    RouteSettings? routeSettings,
    Offset? anchorPoint,
    DrawerAlignment alignment = DrawerAlignment.end,
  }) {
    padding = max(padding, Global.ds(60));
    double titleHeight = Global.ds(56);
    return showGeneralDialog<T>(
      context: context,
      pageBuilder: (BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) => KeyboardDismissOnTap(
        child: Align(
          alignment: alignment == DrawerAlignment.start ? Alignment.centerLeft : Alignment.centerRight,
          child: Container(
            width: width,
            clipBehavior: Clip.antiAlias,
            margin: EdgeInsets.only(top: padding, left: alignment == DrawerAlignment.start ? 0 : padding, right: alignment == DrawerAlignment.end ? 0 : padding),
            decoration: BoxDecoration(
              borderRadius: alignment == DrawerAlignment.start ? BorderRadius.horizontal(right: Radius.circular(radius)) : BorderRadius.horizontal(left: Radius.circular(radius)),
            ),
            child: Column(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              crossAxisAlignment: CrossAxisAlignment.stretch,
              children: [
                Container(
                  height: titleHeight,
                  alignment: Alignment.center,
                  color: ColorUtil.color("#1A263D"),
                  child: Row(
                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
                    children: [
                      Padding(
                        padding: EdgeInsets.symmetric(horizontal: Global.ds(20)),
                        child: Text(title, style: TextStyle(fontSize: Global.ds(18), fontWeight: FontWeight.w700, color: ColorUtil.color("#2CA6E0"))),
                      ),
                      TextButton(
                        onPressed: () => Navigator.pop(context),
                        style: TextButton.styleFrom(
                          padding: EdgeInsets.symmetric(horizontal: Global.ds(20)),
                          fixedSize: Size.fromHeight(Global.ds(56)),
                          textStyle: TextStyle(fontSize: Global.ds(18), height: 1.25),
                          foregroundColor: ColorUtil.color("#2CA6E0"),
                          backgroundColor: Colors.transparent,
                        ),
                        child: Row(
                          mainAxisSize: MainAxisSize.min,
                          mainAxisAlignment: MainAxisAlignment.center,
                          children: alignment == DrawerAlignment.start
                              ? [Icon(Icons.arrow_back_ios, size: Global.ds(18)), const Text("返回")]
                              : [const Text("返回"), Icon(Icons.arrow_forward_ios, size: Global.ds(18))],
                        ),
                      )
                    ],
                  ),
                ),
                Expanded(
                  child: Scaffold(
                    resizeToAvoidBottomInset: resizeToAvoidBottomInset,
                    body: resizeToAvoidBottomInset ? SingleChildScrollView(child: SizedBox(height: Global.windowSize.height - padding - titleHeight, child: child)) : child,
                    backgroundColor: ColorUtil.color("#1A3959"),
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
      barrierDismissible: barrierDismissible,
      barrierColor: opacity > 0 ? Colors.black.withOpacity(opacity) : Colors.transparent,
      barrierLabel: barrierLabel ?? MaterialLocalizations.of(context).modalBarrierDismissLabel,
      useRootNavigator: useRootNavigator,
      anchorPoint: anchorPoint,
      routeSettings: routeSettings,
      transitionDuration: transitionDuration,
      transitionBuilder: transitionBuilder ??
          (BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, Widget child) {
            return SlideTransition(
                position: alignment == DrawerAlignment.start
                    ? Tween<Offset>(begin: const Offset(-1, 0), end: const Offset(0, 0)).animate(animation)
                    : Tween<Offset>(begin: const Offset(1, 0), end: const Offset(0, 0)).animate(animation),
                child: child);
          },
    );
  }

  static Future<T?> dialog<T>({
    required BuildContext context,
    required Widget child,
    Color backgroundColor = Colors.white,
    barrierDismissible = true,
    double opacity = .55,
    bool useRootNavigator = false,
    Duration transitionDuration = const Duration(milliseconds: 300),
    bool resizeToAvoidBottomInset = true,
    RouteTransitionsBuilder? transitionBuilder,
    double? width,
    double? height,
    BorderRadiusGeometry? borderRadius,
    ShapeBorder? shape,
    String? barrierLabel,
    RouteSettings? routeSettings,
    Offset? anchorPoint,
  }) {
    return showGeneralDialog<T>(
      context: context,
      pageBuilder: (BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
        Material material = Material(color: backgroundColor, borderRadius: borderRadius, shape: shape, child: child);
        Widget widget;
        if (width != null || height != null) {
          widget = Center(
            child: SizedBox.fromSize(
              size: width == null
                  ? Size(Global.windowSize.width, height!)
                  : height == null
                      ? Size(width, Global.windowSize.height)
                      : Size(width, height),
              child: material,
            ),
          );
        } else {
          widget = material;
        }
        return ResizeStateBuilder(parent: context, resizeToAvoidBottomInset: resizeToAvoidBottomInset, child: KeyboardDismissOnTap(child: widget));
      },
      barrierDismissible: barrierDismissible,
      barrierColor: opacity > 0 ? Colors.black.withOpacity(opacity) : Colors.transparent,
      barrierLabel: barrierLabel ?? MaterialLocalizations.of(context).modalBarrierDismissLabel,
      useRootNavigator: useRootNavigator,
      anchorPoint: anchorPoint,
      routeSettings: routeSettings,
      transitionDuration: transitionDuration,
      transitionBuilder: transitionBuilder ??
          (BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, Widget child) {
            return ScaleTransition(scale: CurvedAnimation(parent: animation, curve: Curves.fastOutSlowIn), child: child);
          },
    );
  }

  static Future<T?> picker<T>({
    required BuildContext context,
    required Map<String, dynamic> data,
    TextStyle? textStyle,
    Color backgroundColor = Colors.white,
    double opacity = .55,
    String title = '请选择',
    int showItem = 5,
    double? radius,
    double? itemHeight,
  }) {
    double initTitleHeight = Global.ds(50);
    double initItemHeight = itemHeight ?? Global.ds(60);
    List<Map<String, dynamic>> dataList = [data];
    List<int> selectedIndex = [];
    T initial(Map<String, dynamic> data, [int level = 0, int index = 0]) {
      if (dataList.length > level + 1) dataList.removeRange(level + 1, dataList.length);
      if (selectedIndex.length > level) selectedIndex.removeRange(level, selectedIndex.length);
      dynamic value = data.values.elementAt(index);
      selectedIndex.add(index);
      if (value is Map<String, dynamic>) {
        dataList.add(value);
        return initial(value, level + 1);
      } else {
        return value;
      }
    }

    T? selected = initial(data);
    return bottom<T>(
      context: context,
      opacity: opacity,
      backgroundColor: backgroundColor,
      borderRadius: radius == null ? BorderRadius.zero : BorderRadius.vertical(top: Radius.circular(radius)),
      height: showItem * initItemHeight + initTitleHeight,
      child: Column(
        mainAxisSize: MainAxisSize.min,
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: [
          Container(
            height: initTitleHeight,
            alignment: Alignment.center,
            child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: [
                TextButton(
                  onPressed: () => Navigator.pop<T>(context),
                  style: TextButton.styleFrom(
                    padding: EdgeInsets.symmetric(horizontal: Global.ds(20)),
                    foregroundColor: ColorUtil.color("#999999"),
                    fixedSize: Size.fromHeight(initTitleHeight),
                    textStyle: TextStyle(fontSize: Global.ds(16)),
                    backgroundColor: Colors.transparent,
                  ),
                  child: const Text("取消"),
                ),
                Text(title, style: TextStyle(fontSize: Global.ds(20), color: Colors.white, decoration: TextDecoration.none)),
                TextButton(
                  onPressed: () {
                    if (selected != null) Navigator.pop<T>(context, selected);
                  },
                  style: TextButton.styleFrom(
                    padding: EdgeInsets.symmetric(horizontal: Global.ds(20)),
                    foregroundColor: ColorUtil.color("#10BEFF"),
                    fixedSize: Size.fromHeight(initTitleHeight),
                    textStyle: TextStyle(fontSize: Global.ds(16)),
                    backgroundColor: Colors.transparent,
                  ),
                  child: const Text("确定"),
                ),
              ],
            ),
          ),
          Expanded(
            child: Container(
              height: showItem * initItemHeight + Global.ds(40),
              padding: EdgeInsets.symmetric(vertical: Global.ds(20)),
              child: StatefulBuilder(
                builder: (context, stateSetter) => Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  crossAxisAlignment: CrossAxisAlignment.stretch,
                  children: dataList
                      .asMap()
                      .keys
                      .map<Widget>((i) => Flexible(
                            child: Padding(
                              padding: EdgeInsets.symmetric(horizontal: Global.ds(20)),
                              child: NotificationListener<ScrollEndNotification>(
                                onNotification: (notification) {
                                  stateSetter(() {});
                                  return false;
                                },
                                child: ListWheelScrollView(
                                  key: UniqueKey(),
                                  controller: FixedExtentScrollController(initialItem: i < selectedIndex.length ? selectedIndex[i] : 0),
                                  physics: const FixedExtentScrollPhysics(),
                                  overAndUnderCenterOpacity: .25,
                                  itemExtent: initItemHeight,
                                  children: dataList[i].keys.map((key) => Text(key, style: textStyle)).toList(),
                                  onSelectedItemChanged: (index) => selected = initial(dataList[i], i, index),
                                ),
                              ),
                            ),
                          ))
                      .toList(),
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }

  static Future<T?> popup<T>({
    required BuildContext context,
    required List<T> data,
    required IndexedWidgetBuilder itemBuilder,
    T? initialSelected,
    Color backgroundColor = Colors.white,
    double opacity = .55,
    String title = '请选择',
    int showItem = 5,
    double? radius,
    double? itemHeight,
  }) {
    double initTitleHeight = Global.ds(50);
    double initItemHeight = itemHeight ?? Global.ds(30);
    T selected = initialSelected ?? data[0];
    return bottom<T>(
      context: context,
      opacity: opacity,
      backgroundColor: backgroundColor,
      borderRadius: radius == null ? BorderRadius.zero : BorderRadius.vertical(top: Radius.circular(radius)),
      height: showItem * initItemHeight + initTitleHeight,
      child: Column(
        mainAxisSize: MainAxisSize.min,
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: [
          Container(
            height: initTitleHeight,
            alignment: Alignment.center,
            child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: [
                TextButton(
                  onPressed: () => Navigator.pop<T>(context),
                  style: TextButton.styleFrom(
                    padding: EdgeInsets.symmetric(horizontal: Global.ds(15)),
                    foregroundColor: ColorUtil.color("#999999"),
                    fixedSize: Size.fromHeight(initTitleHeight),
                    textStyle: TextStyle(fontSize: Global.ds(16)),
                    backgroundColor: Colors.transparent,
                  ),
                  child: const Text("取消"),
                ),
                Text(title, style: TextStyle(fontSize: Global.ds(20), color: Colors.white, decoration: TextDecoration.none)),
                TextButton(
                  onPressed: () => Navigator.pop<T>(context, selected),
                  style: TextButton.styleFrom(
                    padding: EdgeInsets.symmetric(horizontal: Global.ds(15)),
                    foregroundColor: ColorUtil.color("#10BEFF"),
                    fixedSize: Size.fromHeight(initTitleHeight),
                    textStyle: TextStyle(fontSize: Global.ds(16)),
                    backgroundColor: Colors.transparent,
                  ),
                  child: const Text("确定"),
                ),
              ],
            ),
          ),
          Expanded(
            child: Padding(
              padding: EdgeInsets.symmetric(horizontal: Global.ds(15)),
              child: ListWheelScrollView.useDelegate(
                controller: FixedExtentScrollController(initialItem: data.indexOf(selected)),
                physics: const FixedExtentScrollPhysics(),
                itemExtent: initItemHeight,
                overAndUnderCenterOpacity: .25,
                childDelegate: ListWheelChildBuilderDelegate(
                  childCount: data.length,
                  builder: itemBuilder,
                ),
                onSelectedItemChanged: (index) {
                  selected = data[index];
                },
              ),
            ),
          ),
        ],
      ),
    );
  }

  static Future<T?> bottom<T>({
    required BuildContext context,
    required Widget child,
    Color backgroundColor = Colors.white,
    double opacity = 0,
    double elevation = 0,
    Clip clipBehavior = Clip.antiAlias,
    bool resizeToAvoidBottomInset = true,
    bool isScrollControlled = true,
    bool useRootNavigator = false,
    bool isDismissible = true,
    bool enableDrag = true,
    BorderRadius? borderRadius,
    double? height,
    RouteSettings? routeSettings,
    AnimationController? transitionAnimationController,
    Offset? anchorPoint,
  }) {
    double maxHeight = Global.windowSize.height - Global.windowPadding.top - Global.windowPadding.bottom;
    return showModalBottomSheet<T>(
      context: context,
      builder: (context) => ResizeStateBuilder(
        parent: context,
        resizeToAvoidBottomInset: resizeToAvoidBottomInset,
        child: Ink(
          height: height != null ? min(height, maxHeight) : null,
          decoration: BoxDecoration(color: backgroundColor, borderRadius: borderRadius),
          child: child,
        ),
      ),
      backgroundColor: Colors.transparent,
      elevation: elevation,
      clipBehavior: clipBehavior,
      constraints: BoxConstraints(
        minWidth: 0,
        maxWidth: Global.windowSize.width,
        minHeight: 0,
        maxHeight: maxHeight,
      ),
      shape: RoundedRectangleBorder(borderRadius: borderRadius ?? BorderRadius.zero),
      barrierColor: opacity > 0 ? Colors.black.withOpacity(opacity) : Colors.transparent,
      isScrollControlled: isScrollControlled,
      useRootNavigator: useRootNavigator,
      isDismissible: isDismissible,
      enableDrag: enableDrag,
      routeSettings: routeSettings,
      transitionAnimationController: transitionAnimationController,
      anchorPoint: anchorPoint,
    );
  }
}
